<template>
  <div :class="[{ 'app-container': !this.$route.query.appName }]">
    <div v-if="!this.$route.query.appName" style="padding: 0px, 20px; margin-bottom: 20px; margin-right: 38px">
      <el-row :gutter="16">
        <el-col :span="6">
          <el-card shadow="hover" class="overview-card" style="color: #67c23a; border: 1.5px solid #67c23a">
            <div style="font-size: 13px; margin-bottom: 6px">服务总数</div>
            {{ overview.appCount }}
          </el-card>
        </el-col>
        <el-col :span="6">
          <el-card
            shadow="hover"
            class="overview-card"
            style="
              color: rgb(64, 158, 255);
              border: 1.5px solid rgb(64, 158, 255);
            "
          >
            <div style="font-size: 13px; margin-bottom: 6px">实例总数</div>
            {{ overview.instanceCount }}
          </el-card>
        </el-col>
        <el-col :span="6">
          <el-card
            shadow="hover"
            class="overview-card"
            style="
              color: rgb(230, 162, 60);
              border: 1.5px solid rgb(230, 162, 60);
            "
          >
            <div style="font-size: 13px; margin-bottom: 6px">在线实例</div>
            {{ overview.upCount }}
          </el-card>
        </el-col>
        <el-col :span="6">
          <el-card
            shadow="hover"
            class="overview-card"
            style="
              color: rgb(245, 108, 108);
              border: 1.5px solid rgb(245, 108, 108);
            "
          >
            <div style="font-size: 13px; margin-bottom: 6px">下线实例</div>
            {{ overview.instanceCount - overview.upCount }}
          </el-card>
        </el-col>
      </el-row>
    </div>
    <div class="filter-container" style="margin-bottom: 15px">
      <el-select
        v-model="listQuery.appName"
        placeholder="服务名称"
        filterable
        clearable
        size="small"
        class="filter-item"
        style="width: 300px"
        :disabled="mode === 'single'"
        @keyup.enter.native="handleFilter"
        @change="loadInstances"
      >
        <el-option v-for="item in appOptions" :key="item" :label="item" :value="item" />
      </el-select>
      <el-select
        v-show="listQuery.appName"
        v-model="listQuery.hostPort"
        placeholder="机器实例"
        clearable
        size="small"
        class="filter-item"
        style="width: 180px"
        @keyup.enter.native="handleFilter"
      >
        <el-option v-for="item in instanceOptions" :key="item" :label="item" :value="item" />
      </el-select>
      <el-select
        v-model="listQuery.method"
        placeholder="请求方法"
        clearable
        size="small"
        class="filter-item"
        style="width: 120px"
      >
        <el-option v-for="item in methodOptions" :key="item" :label="item" :value="item" />
      </el-select>
      <el-input
        v-model="listQuery.api"
        placeholder="API"
        size="small"
        class="filter-item"
        style="width: 400px"
        @keyup.enter.native="handleFilter"
      />

      <br>
      <div class="time-container">
        <el-select
          v-model="timeType"
          placeholder="时间类型"
          size="small"
          class="filter-item"
          style="width: 120px"
          @change="changeTimeType"
        >
          <el-option label="固定间隔" :value="1" />
          <el-option label="自定义时间" :value="0" />
        </el-select>

        <el-date-picker
          v-if="timeType === 0"
          v-model="startEnd"
          value-format="timestamp"
          type="datetimerange"
          range-separator="至"
          start-placeholder="开始日期"
          end-placeholder="结束日期"
          align="right"
          size="small"
          class="filter-item"
          :picker-options="pickerOptions"
          @change="onStartEndChange"
        />

        <el-button-group v-else>
          <el-button
            v-for="(item, index) in timeDistants"
            :key="index"
            :type="timeDistantsActive === index ? 'primary' : ''"
            size="small"
            @click="handleClickTimeDistants(index)"
          >
            {{ item.label }}
          </el-button>
        </el-button-group>
      </div>
      <el-button v-waves class="filter-item" type="primary" icon="el-icon-search" size="small" @click="handleFilter">
        查询
      </el-button>
    </div>
    <div class="echart-container">
      <div id="echarts_qps" style="display: inline-block; width: 100%; height: 400px" />
      <div id="echarts_rt" style="display: inline-block; width: 100%; height: 400px" />
    </div>
  </div>
</template>

<script>
import waves from '@/directive/waves'
import * as echarts from 'echarts'
import { getMetricList } from '@/api/metric'
import { listAppNames, getOverview } from '@/api/app'
import { getList } from '@/api/instance'

export default {
  components: {},
  directives: { waves },
  props: {
    mode: {
      type: String,
      default: 'all'
    }
  },
  data() {
    return {
      overview: {},
      methodOptions: [
        'GET',
        'POST',
        'PUT',
        'DELETE',
        'PATCH',
        'HEAD',
        'OPTIONS',
        'CONNECT',
        'TRACE'
      ],
      startEnd: [],
      listQuery: {
        appName: this.$route.query.appName || '',
        method: undefined,
        api: undefined,
        hostPort: undefined,
        start: undefined,
        end: undefined
      },
      appOptions: [],
      listInstances: {
        appName: '',
        pageNo: 1,
        pageSize: 5000
      },
      instanceOptions: [],
      timeType: 1,
      timeDistants: [
        {
          label: '最近 5m',
          value: 5,
          type: 'm'
        },
        {
          label: '30m',
          value: 30,
          type: 'm'
        },
        {
          label: '1h',
          value: 1,
          type: 'h'
        },
        {
          label: '3h',
          value: 3,
          type: 'h'
        },
        {
          label: '6h',
          value: 6,
          type: 'h'
        },
        {
          label: '12h',
          value: 12,
          type: 'h'
        },
        {
          label: '1d',
          value: 1,
          type: 'd'
        },
        {
          label: '3d',
          value: 3,
          type: 'd'
        },
        {
          label: '7d',
          value: 7,
          type: 'd'
        },
        {
          label: '14d',
          value: 14,
          type: 'd'
        },
        {
          label: '30d',
          value: 30,
          type: 'd'
        }
      ],
      timeDistantsActive: 0,
      distantTimer: null,
      pickerOptions: {
        shortcuts: [
          {
            text: '最近 5 分钟',
            onClick(picker) {
              const end = new Date()
              const start = new Date()
              start.setTime(start.getTime() - 5 * 60 * 1000)
              picker.$emit('pick', [start, end])
            }
          },
          {
            text: '最近 10 分钟',
            onClick(picker) {
              const end = new Date()
              const start = new Date()
              start.setTime(start.getTime() - 10 * 60 * 1000)
              picker.$emit('pick', [start, end])
            }
          },
          {
            text: '最近 30 分钟',
            onClick(picker) {
              const end = new Date()
              const start = new Date()
              start.setTime(start.getTime() - 30 * 60 * 1000)
              picker.$emit('pick', [start, end])
            }
          }
        ]
      }
    }
  },
  created() {
    this.fetchOverview()
    this.fetchApps()
  },
  mounted() {
    if (this.$route.query.appName) {
      this.loadInstances(this.$route.query.appName)
    }
    this.fetchData()
  },
  beforeDestroy() {
    clearInterval(this.distantTimer)
  },
  methods: {
    fetchData(arr) {
      const params = {
        ...this.listQuery
      }
      if (this.timeType === 1 && arr) {
        params.start = arr[0]
        params.end = arr[1]
      } else if (this.timeType === 1 && !arr) {
        this.handleFilter()
        return
      }
      var echartWidth =
        document.getElementsByClassName('echart-container')[0].offsetWidth - 80
      var echartsQps = echarts.init(document.getElementById('echarts_qps'))
      getMetricList(params).then((response) => {
        var metricList = response.data
        var timeArr = []
        var pQpsArr = []
        var bQpsArr = []
        var rtArr = []
        for (let i = 0; i < metricList.length; ++i) {
          timeArr[i] = new Date(parseInt(metricList[i].timestamp))
            .toLocaleString()
            .replace(' ', '\n')
          pQpsArr[i] = metricList[i].passQps
          bQpsArr[i] = metricList[i].blockQps
          rtArr[i] = metricList[i].rt
        }
        var option = {
          colorBy: 'series',
          title: {
            text: 'QPS'
          },
          tooltip: {
            trigger: 'axis'
          },
          color: ['#67c23a', '#F56C6C'],
          legend: {
            data: ['通过', '拦截']
          },
          grid: {
            width: echartWidth,
            left: '3%',
            right: '2%',
            bottom: '3%',
            containLabel: true
          },
          xAxis: {
            type: 'category',
            boundaryGap: false,
            data: timeArr
          },
          yAxis: {
            type: 'value'
          },
          series: [
            {
              name: '通过',
              data: pQpsArr,
              type: 'line',
              smooth: true
            },
            {
              name: '拦截',
              data: bQpsArr,
              type: 'line',
              smooth: true
            }
          ]
        }
        echartsQps.setOption(option)
        var echartsRt = echarts.init(document.getElementById('echarts_rt'))
        var rtOption = {
          title: {
            text: '响应时间'
          },
          tooltip: {
            trigger: 'axis'
          },
          grid: {
            width: echartWidth,
            left: '3%',
            right: '2%',
            bottom: '3%',
            containLabel: true
          },
          xAxis: {
            type: 'category',
            boundaryGap: false,
            data: timeArr
          },
          yAxis: {
            type: 'value'
          },
          color: ['#67c23a', '#F56C6C'],
          series: [
            {
              name: '响应时间(ms)',
              data: rtArr,
              type: 'line',
              smooth: true
            }
          ]
        }
        echartsRt.setOption(rtOption)
      })
    },
    fetchOverview() {
      getOverview().then((response) => {
        this.overview = response.data
      })
    },
    fetchApps() {
      listAppNames().then((response) => {
        this.appOptions = response.data
      })
    },
    handleFilter() {
      clearInterval(this.distantTimer)
      if (this.timeType === 1) {
        const distant = this.timeDistants[this.timeDistantsActive]

        // 第一次开始时间设为当前时间
        let timeArr = this.getDistantTime(distant)
        this.fetchData(timeArr)

        // 设置定时器，每隔2秒刷新一次数据
        this.distantTimer = setInterval(() => {
          timeArr = this.getDistantTime(distant)
          this.fetchData(timeArr)
        }, 1500)
      } else {
        this.fetchData()
      }
    },
    fetchInstances() {
      getList(this.listInstances).then((response) => {
        var respItems = response.data.items
        var hostPortArr = []
        for (let index = 0; index < respItems.length; index++) {
          var element = respItems[index]
          hostPortArr[index] = element.ip + ':' + element.port
        }
        this.instanceOptions = hostPortArr
      })
    },
    loadInstances(item) {
      // change 触发事件
      this.listQuery.hostPort = null
      this.instanceOptions = []
      if (item) {
        this.listInstances.appName = item
        this.fetchInstances()
      }
    },
    onStartEndChange(newVal) {
      if (newVal) {
        this.listQuery.start = newVal[0]
        this.listQuery.end = newVal[1]
      } else {
        this.listQuery.start = undefined
        this.listQuery.end = undefined
      }
    },
    // 切换时间类型
    changeTimeType(val) {
      if (val === 1) {
        this.handleClickTimeDistants(this.timeDistantsActive, true)
      } else {
        if (this.startEnd && this.startEnd.length === 0) {
          const now = new Date().getTime()
          this.startEnd = [now - 5 * 60 * 1000, now]
          this.listQuery.start = this.startEnd[0]
          this.listQuery.end = this.startEnd[1]
        }
        clearInterval(this.distantTimer)
      }
    },
    // 点击切换时间间隔
    handleClickTimeDistants(index, trigger) {
      if (index === this.timeDistantsActive && !trigger) return
      this.timeDistantsActive = index
    },
    // 计算时间，在当前查询的时间往前数选定的时间
    getDistantTime(distantObj) {
      const end = new Date().getTime()
      let start = 0

      if (distantObj.type === 'm') {
        start = end - distantObj.value * 60 * 1000
      } else if (distantObj.type === 'h') {
        start = end - distantObj.value * 60 * 60 * 1000
      } else if (distantObj.type === 'd') {
        start = end - distantObj.value * 24 * 60 * 60 * 1000
      }

      return [start, end]
    }
  }
}
</script>

<style scoped>
.filter-container {
  display: flex;
  flex-wrap: wrap;
}

.time-container {
  display: flex;
  padding-right: 15px;
}

.overview-card {
  font-size: 28px;
  text-align: center;
  border-radius: 10px;
}
</style>
